home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / scope / 001-025 / scopedisk8 / superlib / libsrc / xfio.c < prev    next >
C/C++ Source or Header  |  1995-03-18  |  6KB  |  251 lines

  1.  
  2. /*
  3.  *  XFIO.C
  4.  *
  5.  *  Simple File IO with asyncronous READ and WRITE capability
  6.  *  Perfect for protocol transfer applications
  7.  *
  8.  *  xfi = xfopen(name, modes, bufsize)("r", "w", "w+")
  9.  *   n= xfread(xfi, buf, bytes)   ASYNCRONOUS READ
  10.  *  err = xfwrite(xfi, buf, bytes)  ASYNCRONOUS WRITE
  11.  *  err = xfclose(xfi)
  12.  *
  13.  *  RESTRICTIONS:   NO seeking.  You can do one of xfread() or xfwrite()
  14.  *  for a given open XFIle handle (not both).
  15.  *
  16.  *  xfwrite() returns a cumulative error (once an error occurs, it will not
  17.  *  do any more writes).  xfclose() returns the cumulative write error
  18.  *  (since the last write may have been asyncronous and thus the error
  19.  *  unknown at the time).
  20.  *
  21.  *  Two buffers are created each bufsize/2 bytes in size.  for writing,
  22.  *  one buffers is sent asyncronously while the other fills.  For reading,
  23.  *  one buffer is filling while the other is being read.
  24.  */
  25.  
  26. #define XFI    struct _XFI
  27. #define XFBUF    struct _XFBUF
  28. #define MSGPORT     struct MsgPort
  29. #define FH    struct FileHandle
  30. #define STDPKT    struct StandardPacket
  31.  
  32.  
  33. XFBUF {
  34.     long   bufsize;
  35.     long   idx;
  36.     long   max;
  37.     char    buf[4];/*  actually bufsize bytes long */
  38. };
  39.  
  40. XFI {
  41.     char    ro; /*  read only, else write only*/
  42.     char    pend;/*  packet pending*/
  43.     char    err;/*  cumulative error*/
  44.     char    reserved;
  45.     XFBUF   *asbuf;
  46.     XFBUF   *usbuf;
  47.     FH    *fh;
  48.     STDPKT  sp; /*  asyncronous message */
  49.     MSGPORT rp; /*  reply port for pending pkts */
  50. };
  51.  
  52. extern FH *Open();
  53. extern void *malloc(), *FindTask();
  54.  
  55. void *
  56. xfopen(file, mode, bytes)
  57. char *file;
  58. char *mode;
  59. {
  60.     register XFI *xfi = malloc(sizeof(XFI));
  61.     register long nbytes = bytes >> 1;
  62.     int ap = 0;
  63.  
  64.     bzero(xfi, sizeof(XFI));
  65.     if (mode[0] == 'w') {
  66. if (mode[1] == '+') {
  67.     ap = 1;
  68.     if ((xfi->fh = Open(file, 1005)) == NULL)
  69. xfi->fh = Open(file, 1006);
  70.     goto ok;
  71. }
  72. xfi->fh = Open(file, 1006);
  73. goto ok;
  74.     }
  75.     xfi->fh = Open(file, 1005);
  76. ok:
  77.     if (xfi->fh) {
  78. if (ap)
  79.     Seek(xfi->fh, 0, 1);
  80. xfi->fh = (FH *)((long)xfi->fh << 2);
  81. xfi->asbuf = malloc(sizeof(XFBUF) + nbytes);/* a little more    */
  82. xfi->usbuf = malloc(sizeof(XFBUF) + nbytes);/* then we need     */
  83. bzero(xfi->asbuf, sizeof(XFBUF));
  84. bzero(xfi->usbuf, sizeof(XFBUF));
  85. xfi->ro = (mode[0] == 'r');
  86. xfi->asbuf->bufsize = xfi->usbuf->bufsize = nbytes;
  87. xfi->rp.mp_Node.ln_Type = NT_MSGPORT;
  88. xfi->rp.mp_Node.ln_Name = "XFIO-Async";
  89. xfi->rp.mp_Flags = PA_SIGNAL;
  90. xfi->rp.mp_SigBit = AllocSignal(-1);
  91. xfi->rp.mp_SigTask = FindTask(NULL);
  92. NewList(&xfi->rp.mp_MsgList);
  93. if (xfi->ro)
  94.     xfstartasync(xfi, ACTION_READ);
  95.     } else {
  96. free(xfi);
  97. xfi = NULL;
  98.     }
  99.     return(xfi);
  100. }
  101.  
  102. xfclose(xfi)
  103. register XFI *xfi;
  104. {
  105.     int err = 1;
  106.     if (xfi) {
  107. if (xfi->pend) {
  108.     xfi->pend = 0;
  109.     WaitPort (&xfi->rp);
  110.     GetMsg   (&xfi->rp);
  111. }
  112. if (!xfi->ro && xfi->usbuf->idx)
  113.     Write((long)xfi->fh >> 2, xfi->usbuf->buf, xfi->usbuf->idx);
  114. err = xfi->err;
  115. Close((long)xfi->fh >> 2);
  116. free(xfi->asbuf);
  117. free(xfi->usbuf);
  118. FreeSignal(xfi->rp.mp_SigBit);
  119. free(xfi);
  120.     }
  121.     return(err);
  122. }
  123.  
  124. xfgets(xfi, buf, n)
  125. XFI *xfi;
  126. char *buf;
  127. {
  128.     register XFBUF *usbuf = xfi->usbuf;
  129.     register int i, idx;
  130.     if (!xfi->ro)
  131. return(-1);
  132.     --n;
  133.     for (i = 0;;) {
  134. for (idx = usbuf->idx; idx < usbuf->max && i < n; ++idx, ++i) {
  135.     if ((buf[i] = usbuf->buf[idx]) == '\n') {
  136. buf[i] = 0;
  137. usbuf->idx = idx+1;
  138. return(i);
  139.     }
  140. }
  141. usbuf->idx = idx;
  142. buf[i] = 0;
  143. if (i == n)
  144.     return(i);
  145. if (xfi->pend == 0)/* EOF    */
  146.     return(-1);
  147. WaitPort (&xfi->rp);
  148. GetMsg (&xfi->rp);
  149. xfi->pend = 0;
  150. if (xfi->sp.sp_Pkt.dp_Res1 <= 0) {/* EOF    */
  151.     if (i == 0)
  152. return(-1);
  153.     return(i);
  154. }
  155. xfi->asbuf->max = xfi->sp.sp_Pkt.dp_Res1;
  156. xfi->asbuf->idx = 0;
  157. usbuf = xfi->asbuf;/* swap bufs*/
  158. xfi->asbuf = xfi->usbuf;
  159. xfi->usbuf = usbuf;
  160. xfstartasync(xfi, ACTION_READ); /* new async*/
  161.     }
  162. }
  163.  
  164.  
  165. xfread(xfi, buf, n)
  166. XFI *xfi;
  167. char *buf;
  168. {
  169.     register XFBUF *usbuf = xfi->usbuf;
  170.     register int orig = n;
  171.     register int diff;
  172.  
  173.     if (!xfi->ro)
  174. return(0);
  175.     while ((diff = usbuf->max - usbuf->idx) < n) {
  176. movmem(usbuf->buf + usbuf->idx, buf, diff);/* copy entire buf */
  177. buf += diff;
  178. n -= diff;
  179. if (xfi->pend == 0) {
  180.     xfi->usbuf->idx = xfi->usbuf->max;
  181.     return(orig - n);
  182. }
  183. WaitPort (&xfi->rp);
  184. GetMsg (&xfi->rp);
  185. xfi->pend = 0;
  186. if (xfi->sp.sp_Pkt.dp_Res1 <= 0) {/* EOF    */
  187.     xfi->usbuf->idx = xfi->usbuf->max;
  188.     return(orig - n);
  189. }
  190. xfi->asbuf->max = xfi->sp.sp_Pkt.dp_Res1;
  191. xfi->asbuf->idx = 0;
  192. usbuf = xfi->asbuf;/* swap bufs*/
  193. xfi->asbuf = xfi->usbuf;
  194. xfi->usbuf = usbuf;
  195. xfstartasync(xfi, ACTION_READ); /* new async*/
  196.     }
  197.     movmem(usbuf->buf + usbuf->idx, buf, n);
  198.     usbuf->idx += n;
  199.     return(orig);
  200. }
  201.  
  202. xfwrite(xfi, buf, n)
  203. XFI *xfi;
  204. char *buf;
  205. {
  206.     register XFBUF *usbuf = xfi->usbuf;
  207.     register int diff;
  208.  
  209.     if (xfi->ro || xfi->err)
  210. return(1);
  211.     while ((diff = usbuf->bufsize - usbuf->idx) < n) {
  212. movmem(buf, usbuf->buf + usbuf->idx, diff);/*  copy buf*/
  213. buf += diff;
  214. n -= diff;
  215. if (xfi->pend) {
  216.     WaitPort(&xfi->rp);
  217.     GetMsg  (&xfi->rp);
  218.     xfi->pend = 0;
  219.     if (xfi->sp.sp_Pkt.dp_Res1 != xfi->sp.sp_Pkt.dp_Arg3) {
  220. xfi->err = 1;
  221. return(1);
  222.     }
  223. }
  224. usbuf = xfi->asbuf;
  225. xfi->asbuf = xfi->usbuf;
  226. xfi->usbuf = usbuf;
  227. usbuf->idx = 0;
  228. xfstartasync(xfi, ACTION_WRITE);
  229.     }
  230.     movmem(buf, usbuf->buf + usbuf->idx, n);
  231.     usbuf->idx += n;
  232.     return(xfi->err);
  233. }
  234.  
  235. static
  236. xfstartasync(xfi, action)
  237. register XFI *xfi;
  238. {
  239.     xfi->sp.sp_Msg.mn_Node.ln_Name = (char *)&(xfi->sp.sp_Pkt);
  240.     xfi->sp.sp_Pkt.dp_Link = &(xfi->sp.sp_Msg);
  241.     xfi->sp.sp_Pkt.dp_Port = &xfi->rp;
  242.     xfi->sp.sp_Pkt.dp_Type = action;
  243.     xfi->sp.sp_Pkt.dp_Arg1 = xfi->fh->fh_Arg1;
  244.     xfi->sp.sp_Pkt.dp_Arg2 = (long)xfi->asbuf->buf;
  245.     xfi->sp.sp_Pkt.dp_Arg3 = xfi->asbuf->bufsize;
  246.     PutMsg (xfi->fh->fh_Type, &xfi->sp);
  247.     xfi->pend = 1;
  248. }
  249.  
  250.  
  251.